/***************************************************************************
* Lyrics-Player                                                            *
* Copyright (C) 2012 Andrey Derevyanko <derandr@gmail.com>                 *
*                                                                          *
* This program is free software: you can redistribute it and/or modify     *
* it under the terms of the GNU General Public License as published by     *
* the Free Software Foundation, either version 3 of the License, or        *
* (at your option) any later version.                                      *
*                                                                          *
* This program is distributed in the hope that it will be useful,          *
* but WITHOUT ANY WARRANTY; without even the implied warranty of           *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
* GNU General Public License for more details.                             *
*                                                                          *
* You should have received a copy of the GNU General Public License        *
* along with this program.  If not, see <http://www.gnu.org/licenses/>.    *
***************************************************************************/

/*! \file HauptWnd.cpp
 *  \brief The main program window implementation
 *  \author Andrey Derevyanko <derandr@gmail.com>
 *  \version 1.0
 *  \date 11/06/2012
 *  \copyright GNU Public License
 */

#include "HauptWnd.h"

#include <QMessageBox>

HauptWnd::HauptWnd()
{
    lyrTextEdit = new QTextEdit;
    lyrTextEdit->setReadOnly(true);

    playSlider = new Phonon::SeekSlider;
    volumeSlider = new Phonon::VolumeSlider;
    fileDirModel = new QDirModel;
    playListModel = new TrackRecordModel;
    playListView = new playListView_t;
    fileTreeView = new QTreeView;

    playToolBar = new QToolBar("Player Toolbar");
    listSplitter = new QSplitter(Qt::Vertical);
    mainSplitter = new QSplitter(Qt::Horizontal);
    totalTimeLabel = new QLabel("00:00");
    currTimeLabel = new QLabel("00:00");
    currSongName = new QLabel();
    coverInfo = new coverInfoWnd;

    progSettings = new QSettings(tr("StarSoft"), tr("LyrPlayer"));

    playAO = new Phonon::AudioOutput(Phonon::MusicCategory);

    playSlider->setMediaObject(playListModel->mediaObject());
    Phonon::createPath(playListModel->mediaObject(), playAO);
    volumeSlider->setAudioOutput(playAO);

    actionsCreate();
    toolBarsCreate();
    mainMenuCreate();

    fileDirModel->setNameFilters(QStringList() << "*.mp3" << "*.wav" << "*.ogg");
    fileDirModel->setFilter(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
    fileTreeView->setModel(fileDirModel);
    fileTreeView->setColumnHidden(1, true);
    fileTreeView->setColumnHidden(2, true);
    fileTreeView->setColumnHidden(3, true);
    playListView->setModel(playListModel);
    playListView->horizontalHeader()->setStretchLastSection(true);


    QGridLayout * playerGridLayout = new QGridLayout;
    QVBoxLayout * hidariLayout  = new QVBoxLayout;
    QVBoxLayout * migiLayout  = new QVBoxLayout;

    playerGridLayout->addWidget(playSlider, 0, 0, 1, 5);
    playerGridLayout->addWidget(currTimeLabel, 1, 0);
    playerGridLayout->addWidget(totalTimeLabel, 1, 4);
    playerGridLayout->addWidget(currSongName, 1, 1, 1, 3, Qt::AlignHCenter);
    playerGridLayout->addWidget(volumeSlider, 2, 0, 1, 5);

    hidariLayout->addLayout(playerGridLayout, 1);
    listSplitter->addWidget(playListView);
    listSplitter->addWidget(fileTreeView);
    hidariLayout->addWidget(listSplitter, 9);

    migiLayout->addWidget(lyrTextEdit);
    migiLayout->addLayout(coverInfo);

    QWidget * mainWidget = new QWidget;
    mainWidget->setLayout(hidariLayout);
    QWidget * lyrInfoWidget = new QWidget;
    lyrInfoWidget->setLayout(migiLayout);

    mainSplitter->addWidget(mainWidget);
    mainSplitter->addWidget(lyrInfoWidget);
    mainSplitter->setStretchFactor(0, 1);
    mainSplitter->setStretchFactor(1, 2);

    this->addToolBar(Qt::TopToolBarArea, playToolBar);
    this->setCentralWidget(mainSplitter);

    loadSettings();

    connect(fileTreeView, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(add2Play(const QModelIndex &)));
    connect(playListView, SIGNAL(dbClick()), playListModel, SLOT(playThis()));
    connect(playListView, SIGNAL(clicked(const QModelIndex &)), playListModel, SLOT(fileSelect(const QModelIndex &)));

    connect(playListModel, SIGNAL(lyricsAvailable(QString)), SLOT(showLyrics(QString)));
    connect(playListModel, SIGNAL(newTotalTime(qint64)), SLOT(getTotalTime(qint64)));
    connect(playListModel, SIGNAL(newCurrentTime(qint64)), SLOT(getCurrentTime(qint64)));
    connect(playListModel, SIGNAL(newTrackName(QString)), currSongName, SLOT(setText(QString)));
    connect(playListModel, SIGNAL(newFileInfo(trackMetaData_t)), coverInfo, SLOT(newFileInfo(trackMetaData_t)));
    connect(playListModel, SIGNAL(newPlayIcon(playState_t)), SLOT(setStateIcon(playState_t)));
    connect(coverInfo, SIGNAL(saveEditedMetaData(trackMetaData_t)), playListModel, SLOT(newEditedMetaData(trackMetaData_t)));
    connect(playAction, SIGNAL(triggered()), this, SLOT(filePlay()));
    connect(stopAction, SIGNAL(triggered()), this, SLOT(fileStop()));
    connect(closeAction, SIGNAL(triggered()), this, SLOT(close()));
    connect(prevAction, SIGNAL(triggered()), playListModel, SLOT(playPrevTrack()));
    connect(nextAction, SIGNAL(triggered()), playListModel, SLOT(playNextTrack()));
    connect(deleteAction, SIGNAL(triggered()), playListModel, SLOT(fileRemove()));
    connect(burnAction, SIGNAL(triggered()), playListModel, SLOT(clearList()));
    connect(randomAction, SIGNAL(triggered()), playListModel, SLOT(toggleRandomPlay()));
    connect(loadAction, SIGNAL(triggered()), SLOT(loadTrackList()));
    connect(saveAction, SIGNAL(triggered()), SLOT(saveTrackList()));
    connect(rootSelectAction, SIGNAL(triggered()), SLOT(rootSelect()));
    connect(aboutProgAction, SIGNAL(triggered()), SLOT(aboutClicked()));
    connect(aboutQtAction, SIGNAL(triggered()), SLOT(aboutQtClicked()));

    isPlaying = false;
    playListModel->loadModel();
    playListModel->playFirst();
    if (qApp->arguments().count() > 1)
    {
        QString appArgument = qApp->arguments()[1];
        if (appArgument.contains("spl"))
            playListModel->loadModel(appArgument);
        else
        {
            playListModel->addTrack(appArgument);
            playListModel->playLast();
        }
    }
    setWindowIcon(QIcon(":/pics/icon.png"));
    setWindowTitle("LyrPlayer-" + lpVersion::program_version());
}

HauptWnd::~HauptWnd()
{
}

void HauptWnd::add2Play(const QModelIndex & index)
{
    if (!fileDirModel->isDir(index))
        playListModel->addTrack(fileDirModel->filePath(index));
    else
    {
        QDir dirWithFiles(fileDirModel->filePath(index));
        dirWithFiles.setNameFilters(QStringList() << "*.mp3" << "*.wav" << "*.ogg");
        dirWithFiles.setFilter(QDir::Files | QDir::NoDotAndDotDot);
        QDirIterator dir2Add(dirWithFiles, QDirIterator::Subdirectories);
        while (dir2Add.hasNext())
        {
            dir2Add.next();
            playListModel->addTrack(dir2Add.filePath());
        }
    }
}

void HauptWnd::showLyrics(const QString lyrFileString)
{
    QFile lyrFile(lyrFileString);
    QTextStream lyrStream;
    QString lyrString;
    lyrTextEdit->clear();
    if (!lyrFile.exists())
        lyrTextEdit->append("<H1><CENTER>File not found</CENTER></H1>");
    else
    {
        lyrFile.open(QIODevice::ReadOnly);
        lyrStream.setDevice(&lyrFile);
        lyrString = lyrStream.readLine();
        lyrTextEdit->append("Lyrics");
        lyrTextEdit->append("<CENTER><H2>"+lyrString+"</H2>");
        lyrString = lyrStream.readLine();
        lyrTextEdit->append("<H3>"+lyrString+"</H3>");
        while (!lyrStream.atEnd())
        {
            lyrString = lyrStream.readLine();
            lyrTextEdit->append(lyrString);
        }
    }
    QTextCursor cursor(lyrTextEdit->textCursor());
    cursor.movePosition(QTextCursor::Start);
    lyrTextEdit->setTextCursor(cursor);
}

void HauptWnd::filePlay()
{
    if (!isPlaying)
    {
        playListModel->ssPlay();
        playAction->setIcon(QIcon(":/pics/pause.png"));
    }
    else
    {
        playListModel->ssPause();
        playAction->setIcon(QIcon(":/pics/play.png"));
    }
    isPlaying = !isPlaying;
}

void HauptWnd::fileStop()
{
    playListModel->ssStop();
    playAction->setIcon(QIcon(":/pics/play.png"));
    currTimeLabel->setText("00:00");
    isPlaying = false;
}

void HauptWnd::setStateIcon(playState_t state){
    switch (state){
    case st_Play:
        playAction->setIcon(QIcon(":/pics/pause.png"));
        isPlaying = true;
        break;
    case st_Pause:
        playAction->setIcon(QIcon(":/pics/play.png"));
        isPlaying = false;
        break;
    case st_Stop:
        playAction->setIcon(QIcon(":/pics/play.png"));
        currTimeLabel->setText("00:00");
        isPlaying = false;
        break;
    default:
        break;
    }
}

void HauptWnd::closeEvent(QCloseEvent *event)
{
    playListModel->saveModel();
    progSettings->setValue("rootdir", rootDir);
    progSettings->setValue("rndplay", playListModel->getRandomPlay());
    progSettings->setValue("splitters/main", mainSplitter->saveState());
    progSettings->setValue("splitters/list", listSplitter->saveState());
    event->accept();
}

void HauptWnd::getTotalTime(qint64 t_Time)
{
    QTime playerTime(0,0,0,0);
    playerTime = playerTime.addMSecs(t_Time);
    totalTimeLabel->setText(playerTime.toString("h:mm:ss"));
}

void HauptWnd::getCurrentTime(qint64 t_Time)
{
    QTime playerTime(0,0,0,0);
    playerTime = playerTime.addMSecs(t_Time);
    currTimeLabel->setText(playerTime.toString("h:mm:ss"));
}

void HauptWnd::loadTrackList()
{
    QString fileName = QFileDialog::getOpenFileName(this, "Load playlist", QDir::currentPath().toLatin1(),
                                                    "Lyrics Player playlist (*.spl)");
    if (!fileName.isEmpty()) playListModel->loadModel(fileName);
}

void HauptWnd::saveTrackList()
{
    QString fileName = QFileDialog::getSaveFileName(this, "Save playlist", QDir::currentPath().toLatin1(),
                                                    "Lyrics Player playlist (*.spl)");
    if (!fileName.isEmpty()) playListModel->saveModel(fileName);
}

void HauptWnd::actionsCreate()
{
    playAction = new QAction(tr("&Play/Pause"), this);
    stopAction = new QAction(tr("&Stop"), this);
    nextAction = new QAction(tr("&Next"), this);
    prevAction = new QAction(tr("Pre&vious"), this);
    randomAction = new QAction(tr("&Random"), this);
    closeAction = new QAction(tr("&Close"), this);
    deleteAction = new QAction(tr("&Remove"), this);
    burnAction = new QAction(tr("Cle&ar"), this);
    loadAction = new QAction(tr("&Load playlist"), this);
    saveAction = new QAction(tr("&Save playlist"), this);
    rootSelectAction = new QAction(tr("&Root select"), this);
    aboutProgAction = new QAction(tr("&About program"), this);
    aboutQtAction = new QAction(tr("About &Qt"), this);

    randomAction->setCheckable(true);

    playAction->setIcon(QIcon(":/pics/play.png"));
    stopAction->setIcon(QIcon(":/pics/stop.png"));
    closeAction->setIcon(QIcon(":/pics/close.png"));
    nextAction->setIcon(QIcon(":/pics/next.png"));
    prevAction->setIcon(QIcon(":/pics/prev.png"));
    randomAction->setIcon(QIcon(":/pics/random.png"));
    deleteAction->setIcon(QIcon(":/pics/delete.png"));
    burnAction->setIcon(QIcon(":/pics/burn.png"));
    loadAction->setIcon(QIcon(":/pics/load.png"));
    saveAction->setIcon(QIcon(":/pics/save.png"));
    aboutProgAction->setIcon(QIcon(":/pics/icon.png"));
    aboutQtAction->setIcon(QIcon(":/pics/qtlogo.png"));
}

void HauptWnd::toolBarsCreate()
{
    playToolBar->setIconSize(QSize(32, 32));
    playToolBar->addAction(loadAction);
    playToolBar->addAction(saveAction);
    playToolBar->addSeparator();
    playToolBar->addAction(playAction);
    playToolBar->addAction(stopAction);
    playToolBar->addAction(prevAction);
    playToolBar->addAction(nextAction);
    playToolBar->addAction(randomAction);
    playToolBar->addSeparator();
    playToolBar->addAction(deleteAction);
    playToolBar->addAction(burnAction);
    playToolBar->addSeparator();
    playToolBar->addAction(closeAction);
}

void HauptWnd::mainMenuCreate()
{
    fileMenu = menuBar()->addMenu(tr("&File"));
    playMenu = menuBar()->addMenu(tr("&Play"));
    optionsMenu = menuBar()->addMenu(tr("&Options"));
    aboutMenu = menuBar()->addMenu(tr("&About"));

    fileMenu->addAction(loadAction);
    fileMenu->addAction(saveAction);
    fileMenu->addSeparator();
    fileMenu->addAction(deleteAction);
    fileMenu->addAction(burnAction);
    fileMenu->addSeparator();
    fileMenu->addAction(closeAction);

    playMenu->addAction(playAction);
    playMenu->addAction(stopAction);
    playMenu->addAction(prevAction);
    playMenu->addAction(nextAction);
    playMenu->addAction(randomAction);

    optionsMenu->addAction(rootSelectAction);

    aboutMenu->addAction(aboutProgAction);
    aboutMenu->addSeparator();
    aboutMenu->addAction(aboutQtAction);
}

void HauptWnd::rootSelect()
{
    rootDir = QFileDialog::getExistingDirectory(this, tr("Root select"), rootDir);
    fileTreeView->setRootIndex(fileDirModel->index(rootDir));
}

void HauptWnd::loadSettings()
{
    rootDir = progSettings->value("rootdir").toString();
    fileTreeView->setRootIndex(fileDirModel->index(rootDir));
    bool setRnd = progSettings->value("rndplay").toBool();
    playListModel->setRandomPlay(setRnd);
    randomAction->setChecked(setRnd);

    mainSplitter->restoreState(progSettings->value("splitters/main").toByteArray());
    listSplitter->restoreState(progSettings->value("splitters/list").toByteArray());

}

void HauptWnd::aboutClicked()
{
    QMessageBox::about(this, tr("About Lyrics Player"),
                       tr("<h2> Lyrics Player ") + lpVersion::program_version() +
                       tr("</h2> Phonon version: ") + lpVersion::phonon_version() +
                       tr("<p>Backend: ") + lpVersion::backend_version() +
                       tr("<p>ID3Lib: ") + lpVersion::id3lib_version() +
                       tr("<p><b>GNU Public License v3</b>"
                          "<br><p>Andrey Derevyanko"
                          "<p>derandr@gmail.com"
                          "<p>") + QDate::currentDate().toString());
}
